realmode = hvm_realmode(v);
if ( realmode )
- inst_addr = (regs->cs << 4) + regs->eip;
+ inst_addr = regs->cs << 4;
else
- inst_addr = regs->eip;
+ inst_addr = hvm_get_segment_base(current, seg_cs);
+ inst_addr += regs->eip;
memset(inst, 0, MAX_INST_LEN);
if ( inst_copy_from_guest(inst, inst_addr, inst_len) != inst_len ) {
return 0; /* dummy */
}
+static unsigned long svm_get_segment_base(struct vcpu *v, enum segment seg)
+{
+ switch ( seg )
+ {
+ case seg_cs: return v->arch.hvm_svm.vmcb->cs.base;
+ case seg_ds: return v->arch.hvm_svm.vmcb->ds.base;
+ case seg_es: return v->arch.hvm_svm.vmcb->es.base;
+ case seg_fs: return v->arch.hvm_svm.vmcb->fs.base;
+ case seg_gs: return v->arch.hvm_svm.vmcb->gs.base;
+ case seg_ss: return v->arch.hvm_svm.vmcb->ss.base;
+ case seg_tr: return v->arch.hvm_svm.vmcb->tr.base;
+ case seg_gdtr: return v->arch.hvm_svm.vmcb->gdtr.base;
+ case seg_idtr: return v->arch.hvm_svm.vmcb->idtr.base;
+ case seg_ldtr: return v->arch.hvm_svm.vmcb->ldtr.base;
+ }
+ BUG();
+ return 0;
+}
/* Make sure that xen intercepts any FP accesses from current */
static void svm_stts(struct vcpu *v)
hvm_funcs.pae_enabled = svm_pae_enabled;
hvm_funcs.guest_x86_mode = svm_guest_x86_mode;
hvm_funcs.get_guest_ctrl_reg = svm_get_ctrl_reg;
+ hvm_funcs.get_segment_base = svm_get_segment_base;
hvm_funcs.update_host_cr3 = svm_update_host_cr3;
return 0; /* dummy */
}
+static unsigned long vmx_get_segment_base(struct vcpu *v, enum segment seg)
+{
+ unsigned long base;
+
+ BUG_ON(v != current);
+ switch ( seg )
+ {
+ case seg_cs: __vmread(GUEST_CS_BASE, &base); break;
+ case seg_ds: __vmread(GUEST_DS_BASE, &base); break;
+ case seg_es: __vmread(GUEST_ES_BASE, &base); break;
+ case seg_fs: __vmread(GUEST_FS_BASE, &base); break;
+ case seg_gs: __vmread(GUEST_GS_BASE, &base); break;
+ case seg_ss: __vmread(GUEST_SS_BASE, &base); break;
+ case seg_tr: __vmread(GUEST_TR_BASE, &base); break;
+ case seg_gdtr: __vmread(GUEST_GDTR_BASE, &base); break;
+ case seg_idtr: __vmread(GUEST_IDTR_BASE, &base); break;
+ case seg_ldtr: __vmread(GUEST_LDTR_BASE, &base); break;
+ default: BUG(); base = 0; break;
+ }
+ return base;
+}
+
/* Make sure that xen intercepts any FP accesses from current */
static void vmx_stts(struct vcpu *v)
{
hvm_funcs.pae_enabled = vmx_pae_enabled;
hvm_funcs.guest_x86_mode = vmx_guest_x86_mode;
hvm_funcs.get_guest_ctrl_reg = vmx_get_ctrl_reg;
+ hvm_funcs.get_segment_base = vmx_get_segment_base;
hvm_funcs.update_host_cr3 = vmx_update_host_cr3;
#ifndef __ASM_X86_HVM_HVM_H__
#define __ASM_X86_HVM_HVM_H__
+enum segment {
+ seg_cs,
+ seg_ss,
+ seg_ds,
+ seg_es,
+ seg_fs,
+ seg_gs,
+ seg_tr,
+ seg_ldtr,
+ seg_gdtr,
+ seg_idtr
+};
+
/*
* The hardware virtual machine (HVM) interface abstracts away from the
* x86/x86_64 CPU virtualization assist specifics. Currently this interface
* 1) determine whether the guest is in real or vm8086 mode,
* 2) determine whether paging is enabled,
* 3) return the current guest control-register value
+ * 4) return the current guest segment descriptor base
*/
int (*realmode)(struct vcpu *v);
int (*paging_enabled)(struct vcpu *v);
int (*pae_enabled)(struct vcpu *v);
int (*guest_x86_mode)(struct vcpu *v);
unsigned long (*get_guest_ctrl_reg)(struct vcpu *v, unsigned int num);
+ unsigned long (*get_segment_base)(struct vcpu *v, enum segment seg);
/*
* Re-set the value of CR3 that Xen runs on when handling VM exits
return 0; /* force to fail */
}
+static inline unsigned long
+hvm_get_segment_base(struct vcpu *v, enum segment seg)
+{
+ return hvm_funcs.get_segment_base(v, seg);
+}
+
void hvm_stts(struct vcpu *v);
void hvm_set_guest_time(struct vcpu *v, u64 gtime);
void hvm_freeze_time(struct vcpu *v);